﻿using System.Xml.Serialization;

namespace ZOIL.DataModel
{
    public class LinkBase : ILink
    {
        #region Implementation of ILink
        //Nodes können wegen Referenzgleichheit nicht per XmlSerializer serialisiert werden (bzw. können schon, aber dann geht referenz verloren

        #region Node 1
        [XmlIgnore]
        private IPersistable _node1;
        [XmlIgnore]
        public IPersistable Node1
        {
            get
            {
                if (_node1Id != default(long))
                {
                    if (!(_node1 != null && _node1.DatabaseId == _node1Id))
                    {
                        _node1 = DatabaseCollection.Collection.GetPersistable(_node1Id);
                    }

                    _node1Id = default(long);
                }

                return _node1;
            }
            set
            {
                _node1 = value;
                _node1Id = default(long);
            }
        }

        [Db4oIgnore] 
        private long _node1Id = default(long);
        [XmlElement("Node1")]
        public long Node1Id
        {
            get { return Node1 != null ? Node1.DatabaseId : default(long); }
            set
            {
                _node1Id = value;
                _node1 = null;
            }
        }
        #endregion

        #region Node 2
        [XmlIgnore]
        private IPersistable _node2;
        [XmlIgnore]
        public IPersistable Node2
        {
            get
            {
                if (_node2Id != default(long))
                {
                    if (!(_node2 != null && _node2.DatabaseId == _node2Id))
                    {
                        _node2 = DatabaseCollection.Collection.GetPersistable(_node2Id);
                    }
                    _node2Id = default(long);
                }

                return _node2;
            }
            set
            {
                _node2 = value;
                _node2Id = default(long);
            }
        }

        [Db4oIgnore]
        private long _node2Id = default(long);
        [XmlElement("Node2")]
        public long Node2Id
        {
            get { return Node2 != null ? Node2.DatabaseId : default(long); }
            set
            {
                _node2Id = value;
                _node2 = null;
            }
        }
        #endregion

        #endregion

        #region Equality members

        protected bool Equals(LinkBase other)
        {
            if (other == null)
            {
                return false;
            }
            return Node1.DatabaseId == other.Node1.DatabaseId && Node2.DatabaseId == other.Node2.DatabaseId;
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <param name="obj">The object to compare with the current object. </param>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != this.GetType())
            {
                return false;
            }
            return Equals((LinkBase) obj);
        }

        /// <summary>
        /// Serves as a hash function for a particular type. 
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        public override int GetHashCode()
        {
            unchecked
            {
                return ((_node1 != null ? _node1.DatabaseId.GetHashCode() : 0)*397) ^ (_node2 != null ? _node2.DatabaseId.GetHashCode() : 0);
            }
        }

        #endregion
    }
}